﻿using System;
using Microsoft.SharePoint;
using MS.InformationManagement.Support;
using MS.InformationManagement.Support.Constants;
using MS.InformationManagement.Core.SystemUser;
using MS.InformationManagement.Core.Support;
using System.Collections.Generic;
using System.Linq;

namespace MS.InformationManagement.Records.Receivers
{
    /// <summary>
    /// List Item Events
    /// </summary>
    public class SectionReceiver : SPItemEventReceiver
    {
        /// <summary>
        /// An item was added.
        /// </summary>
        public override void ItemAdded(SPItemEventProperties properties)
        {
            base.ItemAdded(properties);
            if (properties.List.Title.Equals("Secciones"))
                try
                {
                    this.EventFiringEnabled = false;
                    int newParentCode = 0;                    
                    string newParentName = string.Empty;
                    string currentSectionName = properties.ListItem.Title;

                    if (properties.ListItem[CustomSiteColumns.FIELD_SECCION_PADRE_INTERNAL_NAME] != null)
                    {
                        SPFieldLookupValue newParentSection = new SPFieldLookupValue(properties.ListItem[CustomSiteColumns.FIELD_SECCION_PADRE_INTERNAL_NAME].ToString());
                        newParentCode = newParentSection.LookupId;
                        newParentName = newParentSection.LookupValue;
                    }

                    SPWeb currentWeb = properties.Web;

                    string groupOwnerValue = properties.ListItem[CustomSiteColumns.FIELD_USER_IN_CHARGE].ToString();
                    int groupOwnerId = Convert.ToInt32(groupOwnerValue.Substring(0, groupOwnerValue.LastIndexOf(';')));
                    SPUser groupOwner = currentWeb.SiteUsers.GetByID(groupOwnerId);

                    if(!GroupExists(currentWeb.SiteGroups,properties.ListItem.Title))
                        currentWeb.SiteGroups.Add(properties.ListItem.Title, groupOwner, groupOwner, string.Format("Grupo usuarios para la dependencia/sección {0}", properties.ListItem.Title));

                    SPGroup createdGroup = currentWeb.SiteGroups[properties.ListItem.Title];
                    SPFieldUserValue groupValue = new SPFieldUserValue { LookupId = createdGroup.ID };
                    properties.ListItem[CustomSiteColumns.FIELD_SECURITY_GROUP] = groupValue;
                    properties.ListItem.SystemUpdate();

                    //Adding read permissions for new group
                    SPSecurity.RunWithElevatedPrivileges(delegate()
                    {
                        using (SPSite site = new SPSite(currentWeb.Site.ID))
                        {
                            using (SPWeb web = site.OpenWeb())
                            {
                                var newGroup = currentWeb.SiteGroups[properties.ListItem.Title];
                                SPRoleDefinition oRole = currentWeb.RoleDefinitions.GetByType(SPRoleType.Reader);
                                SPRoleAssignment roleAssignment = new SPRoleAssignment(newGroup);
                                roleAssignment.RoleDefinitionBindings.Add(oRole);
                                currentWeb.RoleAssignments.Add(roleAssignment);
                                currentWeb.Update();
                                Guid newLibraryId = UserLibraryHelper.CreateDocumentLibraryWithGroupPrivileges(properties.ListItem.Title, web, properties.ListItem.Title);

                                //Add contribute permission for document library
                                var contributeGroup = currentWeb.SiteGroups["CONTRIBUYENTES GESTION DOCUMENTAL"];
                                SPRoleDefinition contributeRole = currentWeb.RoleDefinitions.GetByType(SPRoleType.Contributor);
                                SPRoleAssignment contributeRoleAssignment = new SPRoleAssignment(contributeGroup);
                                contributeRoleAssignment.RoleDefinitionBindings.Add(contributeRole);
                                SPList newList = web.Lists[newLibraryId];
                                newList.RoleAssignments.Add(contributeRoleAssignment);
                                newList.Update();
                                web.Update();


                            }
                        }
                    });

                    SPSite currentSite = currentWeb.Site;
                    if (newParentCode != 0) { AddUsersToNewStructure(newParentCode, newParentName, currentSectionName, ref currentSite); }

                }
                catch (Exception ex)
                {
                    Logger.LogException(ex, Microsoft.SharePoint.Administration.EventSeverity.Error,
                            SPDiagnosticsAreas.SHAREPOINTFOUNDATION, SPDiagnosticsAreas.SharepointFoundationDiagnosticsCategories.WEBPARTS);
                }
                finally
                {
                    this.EventFiringEnabled = true;
                }

        }

        /// <summary>
        /// An item was updated.
        /// </summary>
        public override void ItemUpdated(SPItemEventProperties properties)
        {
            base.ItemUpdated(properties);
            if (properties.List.Title.Equals("Secciones"))
                try
                {
                    this.EventFiringEnabled = false;
                    SPWeb currentWeb = properties.Web;

                    string groupName = properties.ListItem.Title;
                    string groupValue = properties.ListItem[CustomSiteColumns.FIELD_SECURITY_GROUP].ToString();
                    int groupID = Convert.ToInt32(groupValue.Substring(0, groupValue.LastIndexOf(';')));
                    
                    SPGroup sectionGroup = currentWeb.SiteGroups.GetByID(groupID);

                    string oldSectionName = sectionGroup.Name;
                    string newSectionName = properties.ListItem.Title;

                    sectionGroup.Name = properties.ListItem.Title;

                    string groupOwnerValue = properties.ListItem[CustomSiteColumns.FIELD_USER_IN_CHARGE].ToString();
                    int groupOwnerId = Convert.ToInt32(groupOwnerValue.Substring(0, groupOwnerValue.LastIndexOf(';')));
                    
                    SPUser groupOwner = currentWeb.SiteUsers.GetByID(groupOwnerId);
                    sectionGroup.Owner = groupOwner;
                    sectionGroup.Description = string.Format("Grupo usuarios para la dependencia/sección {0}", properties.ListItem.Title);
                    sectionGroup.Update();

                    using (SPSite currentSite = properties.OpenSite()){
                        UpdateUserDependencies(oldSectionName, newSectionName, currentSite);
                    }
                    

                }
                catch (Exception ex)
                {
                    Logger.LogException(ex, Microsoft.SharePoint.Administration.EventSeverity.Error,
                            SPDiagnosticsAreas.SHAREPOINTFOUNDATION, SPDiagnosticsAreas.SharepointFoundationDiagnosticsCategories.WEBPARTS);
                }
                finally
                {
                    this.EventFiringEnabled = true;
                }
        }


        /// <summary>
        /// An item is being updated.
        /// </summary>
        public override void ItemUpdating(SPItemEventProperties properties)
        {
            base.ItemUpdating(properties);
            if (properties.List.Title.Equals("Secciones"))
                try
                {
                    this.EventFiringEnabled = false;
                    SPListItem ItemSection = properties.ListItem;
                    string oldPerfilName = ItemSection.Title;
                    string newPerfilName = properties.AfterProperties["Title"].ToString();
                    if (oldPerfilName != newPerfilName)
                    {
                        properties.ErrorMessage = string.Format("No es permitido modificar el nombre de la seccion {0}", oldPerfilName);
                        properties.Status = SPEventReceiverStatus.CancelWithError;
                        properties.Cancel = true; 
                        //throw new Exception("No es permitido modificar el nombre de la seccion");
                    }
                    else
                    {
                        int newParentCode = 0;
                        int oldParentCode = 0;
                        string oldParentName = string.Empty;
                        string newParentName = string.Empty;

                        string currentSectionName = properties.ListItem.Title;
                        if (properties.ListItem[CustomSiteColumns.FIELD_SECCION_PADRE_INTERNAL_NAME] != null)
                        {
                            SPFieldLookupValue oldParentSection = new SPFieldLookupValue(properties.ListItem[CustomSiteColumns.FIELD_SECCION_PADRE_INTERNAL_NAME].ToString());
                            oldParentCode = oldParentSection.LookupId;
                            oldParentName = oldParentSection.LookupValue;
                        }

                        if (properties.AfterProperties[CustomSiteColumns.FIELD_SECCION_PADRE_INTERNAL_NAME] != null)
                        {
                            newParentCode = System.Convert.ToInt32(properties.AfterProperties[CustomSiteColumns.FIELD_SECCION_PADRE_INTERNAL_NAME]);
                            SPListItem newParentListItem = properties.List.GetItemById(newParentCode);
                            newParentName = newParentListItem.Title;
                        }

                        if (oldParentCode != newParentCode)
                        {
                            SPSite currentSite = properties.Web.Site;
                            if (oldParentCode != 0) { RemoveUsersFromOldStructure(oldParentCode, oldParentName, currentSectionName, ref currentSite); }
                            if (newParentCode != 0) { AddUsersToNewStructure(newParentCode, newParentName, currentSectionName, ref currentSite); }
                        }

                    }
                }
                catch (Exception ex)
                {
                    Logger.LogException(ex, Microsoft.SharePoint.Administration.EventSeverity.Error,
                            SPDiagnosticsAreas.SHAREPOINTFOUNDATION, SPDiagnosticsAreas.SharepointFoundationDiagnosticsCategories.WEBPARTS);
                    throw ex;
                }
                finally
                {
                    this.EventFiringEnabled = true;
                }

        }

        /// <summary>
        /// An item was deleted.
        /// </summary>
        public override void ItemDeleted(SPItemEventProperties properties)
        {
            base.ItemDeleted(properties);
            try
            {
                this.EventFiringEnabled = false;
                string groupName = properties.ListItem.Title;
                    SPWeb currentWeb = properties.Web;
                    currentWeb.SiteGroups.Remove(groupName);
            }
            catch (Exception ex)
            {
                Logger.LogException(ex, Microsoft.SharePoint.Administration.EventSeverity.Error,
                        SPDiagnosticsAreas.SHAREPOINTFOUNDATION, SPDiagnosticsAreas.SharepointFoundationDiagnosticsCategories.WEBPARTS);
            }
            finally
            {
                this.EventFiringEnabled = true;
            }

        }

        /// <summary>
        /// An item is been deleted
        /// </summary>
        public override void ItemDeleting(SPItemEventProperties properties)
        {
            base.ItemDeleting(properties);
            if (properties.List.Title.Equals("Secciones"))
            {
                try
                {
                    this.EventFiringEnabled = false;
                    //if (!properties.Web.CurrentUser.IsSiteAdmin)
                    //{
                    properties.Cancel = true;
                    properties.ErrorMessage = string.Format("No es posible eliminar items de esta lista."
                        , properties.Web.CurrentUser.LoginName);
                    //}
                }
                catch (Exception ex)
                {
                    Logger.LogException(ex, Microsoft.SharePoint.Administration.EventSeverity.Error,
                         SPDiagnosticsAreas.SHAREPOINTFOUNDATION, SPDiagnosticsAreas.SharepointFoundationDiagnosticsCategories.WEBPARTS);
                    throw;
                }
                finally { this.EventFiringEnabled = true; }
            }
        }

        private void GetNextParentSection(int currentSectionID, ref string parentSectionName, ref int parentSectionID, SPWeb web)
        {
            SPList targetList = web.Lists.TryGetList(GlobalConstants.LIST_BIBLIOTECA_SECCION);
            if (targetList == null) { throw new Exception("No existe la lista de secciones en el sistema."); }

            SPListItem item = targetList.GetItemById(currentSectionID);
            if (item == null) { throw new Exception(string.Format("No exite una sección con ID {0}", currentSectionID)); }

            if (item[CustomSiteColumns.FIELD_SECCION_PADRE_INTERNAL_NAME] != null)
            {
                SPFieldLookupValue parentSection = new SPFieldLookupValue(item[CustomSiteColumns.FIELD_SECCION_PADRE_INTERNAL_NAME].ToString());
                parentSectionName = parentSection.LookupValue;
                parentSectionID = parentSection.LookupId;
            }
        }

        private void AddUsersToNewStructure(int sectionID, string sectionName, string currentSectionName, ref SPSite site)
        {
            string parentSectionName = string.Empty;
            int parentSectionID = 0;
            using (SPWeb web = site.OpenWeb())
            {
                AddUsersToGroup(currentSectionName, sectionName, web);
                GetNextParentSection(sectionID, ref parentSectionName, ref parentSectionID, web);
            }
            if (parentSectionID != 0) { AddUsersToNewStructure(parentSectionID, parentSectionName, currentSectionName, ref site); }
        }

        private void AddUsersToGroup(string groupName, string sectionName, SPWeb web)
        {
            Dictionary<string, string> currentSectionUsers = PeopleHelper.GetUsersByProperty(GlobalConstants.UP_DEPARTMENT, sectionName, web.Site);
            SPGroup currentSectionGroup = web.Groups[groupName];
            SPUserCollection groupUsers = currentSectionGroup.Users;

            foreach (KeyValuePair<string, string> currentUser in currentSectionUsers)
            {
                currentSectionGroup.AddUser(web.SiteUsers[currentUser.Key]);
            }

            web.AllowUnsafeUpdates = true;
            currentSectionGroup.Update();
            web.AllowUnsafeUpdates = false;
        }

        public static bool GroupExists(SPGroupCollection groups, string name)
        {
            if (string.IsNullOrEmpty(name) ||
                (name.Length > 255) ||
                (groups == null) ||
                (groups.Count == 0))
                return false;
            else
                return (groups.GetCollection(new String[] { name }).Count > 0);
        }

        private static void UpdateUserDependencies(string oldDependecyName, string newDependencyName, SPSite site) {
            Dictionary<string, string> userDictionary = PeopleHelper.GetUsersByProperty(GlobalConstants.UP_DEPARTMENT, oldDependecyName, true, site);
            foreach (KeyValuePair<string, string> user in userDictionary) {
                PeopleHelper.UpdatePropertyUserProfile(GlobalConstants.UP_DEPARTMENT, newDependencyName, user.Key, site);
            }
        }


        //----------------------------------------------

        private void RemoveUsersFromOldStructure(int sectionID, string sectionName, string currentSectionName, ref SPSite site)
        {
            string parentSectionName = string.Empty;
            int parentSectionID = 0;
            using (SPWeb web = site.OpenWeb())
            {
                RemoveUsersFromGroup(currentSectionName, sectionName, web);
                GetNextParentSection(sectionID, ref parentSectionName, ref parentSectionID, web);
            }
            if (parentSectionID != 0) { RemoveUsersFromOldStructure(parentSectionID, parentSectionName, currentSectionName, ref site); }
        }

        private void RemoveUsersFromGroup(string groupName, string sectionName, SPWeb web)
        {
            Dictionary<string, string> currentSectionUsers = PeopleHelper.GetUsersByProperty(GlobalConstants.UP_DEPARTMENT, sectionName, web.Site);
            SPGroup currentSectionGroup = web.Groups[groupName];
            SPUserCollection groupUsers = currentSectionGroup.Users;

            var commonusers = (from SPUser groupUser in groupUsers
                               join sectionUser in currentSectionUsers
                                   on groupUser.LoginName.ToLower() equals sectionUser.Key.ToLower()
                               select groupUser.LoginName)
                               .Except(new string[] { (currentSectionGroup.Owner as SPUser).LoginName })
                               .ToArray();

            currentSectionGroup.Users.RemoveCollection(commonusers);

            web.AllowUnsafeUpdates = true;
            currentSectionGroup.Update();
            web.AllowUnsafeUpdates = false;

        }

        
    }
}
